I2C EEPROM
Brain のブートシークエンスは i.MX 28 世代では I2C から開始される。Boot ROM による I2C からのブートには 64KB のサイズ制限があり、中身の置き換えには非常に小さなバイナリが必要になる。 EEPROM 仕様推測
足が出ていない → SON
2x3 → ON Semi か Rohm
厚み 0.5mm = Rohm の VSON
100 kHz
型番は BR24G32, 4KB
code: 刻印
4G3 <- 型番
2 3 <- 型番続き, Lot?
X83 <- Lot
EEPROM に入る U-Boot の検討
EEPROM の中身を置き換えるにあたり、まずは U-Boot が入らないかを考える。
u-boot.bin
(サイズ基準はコミット 8f3049f のコードで生成される u-boot.sb 516K とする)
Thumb を使う 466K (-50K)
ロゴを消す 180K (-286K)
SYS_LONGHELP などコマンド系を削る 148K (-32K)
いろいろ削る 134K (-14K)
shell すら無効にしたりする 126K (-8K)
無理!
u-boot-spl.bin
何もしなくても u-boot-spl.bin は 10K くらい
結論
無理っぽそう
解析: ロジアナでダンプ
一度のシーケンシャル読み込みで 128 Bytes 読む
7回バースト読み込みをして合計 896 Bytes 読む
code:stdout
$ ./extract.py pwsh1_boot.csv
* Parse summary *
Chunk 1: address=0, length=128
Chunk 2: address=128, length=128
Chunk 3: address=256, length=128
Chunk 4: address=384, length=128
Chunk 5: address=512, length=128
Chunk 6: address=640, length=128
Chunk 7: address=768, length=128
Total length = 896
Saleae Logic 2 のダンプデータをパースするやつは lab にある 解析: ダンプの内容を読む (mkimage)
EEPROM の内容は Boot Stream (.sb file) で、U-Boot が生成する u-boot.sb と同様の構造を持つ。U-Boot mkimage を使うと内容が解析できる。今回は末尾のハッシュがギリギリ切れているせいかパースできなかった。
code: mkimageのビルドと呼び出し.sh
cd u-boot-brain
ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- make tools
./tools/mkimage -l ${PARSED_BINARY}
解析: ダンプの内容を読む (Rockbox sbtoelf)
Rockbox は SigmaTel 時代の近縁 SoC STMP3xxx を解析し "sbtoelf" を開発した。これにチェックサム無視でパースさせる。
"File too small (should be at least 912 bytes)" と言われた場合は末尾に dd でゼロを追加する。
code: rockbox_sbtoelf.sh
git clone git@github.com:Rockbox/rockbox.git
cd rockbox/utils/imxtools/sbtools
make
./sbtoelf -o extracted_ -dzn --ignore-sha1 ${PATH_TO_SB}
code: sbtoelf_log
$ ./sbtoelf -o extracted_ -dzn --ignore-sha1 ~/dev/brain/lab/eeprom/padded.bin
Basic info:
SB version: 1.1
Header SHA-1: 2B 7C C5 BE 35 A2 82 8F E5 02 47 1E 44 BC CC 24 EA AB D2 96 Ok
Flags: 1
Total file size : 912
Sizes and offsets:
# of encryption keys = 1
# of sections = 1
Versions
Random 1: 1E 03 73 67 74 6C
Random 2: 1E 2A 87 5A 43 64
Creation date/time = Wed May 16 01:21:42 2012
Product version = 999.999.999
Component version = 999.999.999
Drive tag = 0
First boot tag offset = 9
First boot section ID = 0x0000beef
Encryption keys
Key 0
Key: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
CBC-MAC: F9 4A 4B AD 41 79 BD B4 45 10 1D B5 C2 EF AC 6C
DEK
Entry 0
Encrypted key: 81 0A B0 B1 ED 68 8C D5 65 74 C7 72 B8 4B 81 DC
CBC-MAC : F9 4A 4B AD 41 79 BD B4 45 10 1D B5 C2 EF AC 6C Match
Decrypted key: 90 D8 61 73 7B F3 AC 54 79 F4 D6 C1 90 A7 92 F7
Summary:
Real key: 90 D8 61 73 7B F3 AC 54 79 F4 D6 C1 90 A7 92 F7
IV : 2B 7C C5 BE 35 A2 82 8F E5 02 47 1E 44 BC CC 24
Sections
Section '____'
pos = a0 - 370
len = 2d0
flags = 1 Boot Section (Encrypted)
LOAD | addr=0x0000e440 | len=0x00000260 | crc=0xd040caf4 Ok
FILL | addr=0x0000e6a0 | len=0x00000114 | pattern=0x00000000
LOAD | addr=0x0000e400 | len=0x00000020 | crc=0x37570c11 Ok
f=1 CALL | addr=0x0000e400 | arg=0x00000000 MODE | mod=0x00000009
Final signature:
Encrypted SHA-1:
C4 3A 7B 08 1E F8 0F D0 82 BE 94 D4 A9 DA B8 F2
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
File SHA-1:
0D 61 FE 70 94 5A 54 8B FF DB 53 AC A1 0B 1F 4B 3F 88 64 4F Failed
Warning: SHA-1 mismatch ignored per flags
Write boot section ____ to extracted_____.0.elf
Write command file to extracted_make.db
SB File
+-Version: 1.1
+-Flags: 1
+-Drive Tag: 0
+-First Boot Section ID: 0000beef (____)
+-Timestamp: 0x16323743ef980 (Wed May 16 01:21:42 2012)
+-Product Version: 999.999.999
+-Component Version: 999.999.999
+-Section
| +-Identifier: 0000beef (____)
| +-Type: Boot Section (Encrypted)
| +-Alignment: 32 (bytes)
| +-Other Flags: 0
| +-Instructions
| | +-LOAD | addr=0x0000e440 | len=0x00000260
| | +-FILL | addr=0x0000e6a0 | len=0x00000114 | pattern=0x00000000
| | +-LOAD | addr=0x0000e400 | len=0x00000020
| | +-CALL | addr=0x0000e400 | arg=0x00000000
| | +-MODE | mod=0x00000000
解析結果
LOAD | addr=0x0000e440 | len=0x00000260 0xe440 に機械語列をロード
FILL | addr=0x0000e6a0 | len=0x00000114 | pattern=0x00000000 0xe6a0 から長さ 0x114 を zero fill (bss?)
LOAD | addr=0x0000e400 | len=0x00000020 0xe400 に IVT をロード
[f=1] CALL | addr=0x0000e400 | arg=0x00000000 0xe400 (IVT) を call し、IVT で指定された 0xe61d (?) へジャンプ
MODE | mod=0x00000009 eMMC (SSP0) へモード切り替え
code: disassembly
header.tag
0000e400 d1 db D1h
header.length
0000e401 00 20 dw 2000h
header.version
0000e403 40 db 40h
entry
0000e404 1d e6 00 00 addr FUN_0000e61c+1
reserved1
0000e408 00 00 00 00 ddw 0h
dcd
0000e40c 00 00 00 00 ddw 0h
boot data
0000e410 00 00 00 00 ddw 0h
self
0000e414 00 e4 00 00 ddw E400h
csf
0000e418 00 00 00 00 ddw 0h
reserved2
0000e41c 00 00 00 00 ddw 0h
機械語列の中では SSP0 ~ 3 の HW_SSP_DLL_CTRL にある REF_UPDATE_INT? を書いてディレイを追加している?ように見える。
eMMC に飛ぶだけの SB の作り方
MODE SD_SSP0 の呼び出しはもともと EEPROM に入っているが、U-Boot で自力で作るには以下の手順に従う。
code: emmc_sb.sh
export ARCH=arm
export CROSS_COMPILE=arm-linux-gnueabi-
cd ${PATH_TO_UBOOT_BRAIN}
make -jnproc mx28evk_defconfig
make -jnproc tools
cat <<EOF > emmc.cfg
DISPLAYPROGRESS
SECTION 0x0 BOOTABLE
TAG LAST
MODE SD_SSP0
EOF
./tools/mkimage -A arm -O u-boot -T mxsimage -d /dev/null -n emmc.cfg emmc.sb
※1. -d /dev/null は本来不要だが渡さないとエラーで落ちる